<?php
declare(strict_types=1);

namespace Gwl\Framework\Foundation\Http;

use Gwl\Framework\Foundation\Application;
use Gwl\Framework\Foundation\Bootstrap\BootProviders;
use Gwl\Framework\Foundation\Bootstrap\LoadConfiguration;
use Gwl\Framework\Foundation\Bootstrap\RegisterFacades;
use Gwl\Framework\Foundation\Bootstrap\RegisterProviders;
use Gwl\Framework\Pipeline\Pipeline;
use Gwl\Framework\Routing\Router;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class Kernel
{
    protected $app;
    protected $router;

    protected $middlewares = [];

    protected $bootstrappers = [
        LoadConfiguration::class,
        RegisterFacades::class,
        RegisterProviders::class,
        BootProviders::class
    ];

    public function __construct(Application $app, Router $router)
    {
        $this->app = $app;
        $this->router = $router;
    }

    /**
     * @param Request $request
     * @return Response
     */
    public function handle(Request $request)
    {
        $this->app->set(Request::class, $request);
        $resp =  $this->sendRequestThroughRouter($request);
        if ($resp instanceof Response){
            return $resp;
        }elseif (is_array($resp) ||$resp instanceof \ArrayIterator || $resp instanceof \JsonSerializable )
        {
            return Response::create(json_encode($resp),200);
        }
        return Response::create($resp, 200);
    }

    protected function sendRequestThroughRouter(Request $request)
    {
        $this->app->withBootstrap($this->bootstrappers);
        return (new Pipeline($this->app))->send($request)
            ->through($this->middlewares)
            ->then($this->dispatchToRouter());
    }

    protected function dispatchToRouter()
    {
        return function ($request) {
            $this->app->set('request', $request);
            return $this->router->dispatch($request);
        };
    }
}
